06. Testing Coroutine Timing

L5 P4 A05 Testing Coroutine Timing V3

In this step you'll use TestCouroutineDispatcher's pauseDispatcher and resumeDispatcher methods. Using these methods, you'll write a test that makes sure the loading indicator is shown when the statistics are loading, and then disappears once the statistics are loaded.

Step 1: Create a loading indicator test

  1. Copy the code below and run the test. This test fails.

StatisticsViewModelTest.kt

@Test
fun loadTasks_loading() {

    // Load the task in the view model.
    statisticsViewModel.refresh()

    // Then progress indicator is shown.
    assertThat(statisticsViewModel.dataLoading.getOrAwaitValue(), `is`(true))

    // Then progress indicator is hidden.
    assertThat(statisticsViewModel.dataLoading.getOrAwaitValue(), `is`(false))
}

The test above doesn't really make sense because it's testing that dataLoading is both true and false at the same time.

  1. Look at the failure and see that the test fails because of the first assert statement.

This test fails because the entire refresh() method completes before the loading indicator assert statements are made.

Step 2: Pause and Resume the dispatcher

  1. Update the test to use pauseDispatcher and resumeDispatcher so that you pause before executing the coroutine, check that the loading indicator is shown, then resume and check that the load is gone:

StatisticsViewModelTest.kt

@Test
fun loadTasks_loading() {
    // Pause dispatcher so you can verify initial values.
    mainCoroutineRule.pauseDispatcher()

    // Load the task in the view model.
    statisticsViewModel.refresh()

    // Then assert that the progress indicator is shown.
    assertThat(statisticsViewModel.dataLoading.getOrAwaitValue(), `is`(true))

    // Execute pending coroutines actions.
    mainCoroutineRule.resumeDispatcher()

    // Then assert that the progress indicator is hidden.
    assertThat(statisticsViewModel.dataLoading.getOrAwaitValue(), `is`(false))
}
  1. Run the test and see that it passes now.

If you need even more fine-grained timing control, TestCouroutineDispatcher provides that as well. Check out:


Excellent - you've learned how to write coroutine tests that use TestCoroutineDispatcher's ability to pause and resume coroutine execution. This gives you more control when writing tests that require precise timing.